package qc.module.ehs.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import qc.common.core.enums.ResourceStatusFlagEnum;
import qc.common.core.exception.QCPromptException;
import qc.common.core.unify.QCUnifyReturnValue;
import qc.common.core.utils.IdentifierUtil;
import qc.common.core.utils.StringSplitUtil;
import qc.module.ehs.dto.check.*;
import qc.module.ehs.dto.unit.EhsUnitDto;
import qc.module.ehs.dto.unitcategory.TplUnitCategoryDto;
import qc.module.ehs.entity.*;
import qc.module.ehs.mapper.EhsCheckGroupMapper;
import qc.module.ehs.mapper.EhsCheckItemMapper;
import qc.module.ehs.mapper.EhsCheckTableMapper;
import qc.module.ehs.repository.EhsCheckGroupRepository;
import qc.module.ehs.repository.EhsCheckItemRepository;
import qc.module.ehs.repository.EhsCheckTableRepository;
import qc.module.ehs.repository.EhsTaskCategoryRepository;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 检查表信息接口Service
 *
 * @author QuCheng Tech
 * @create 2024/10/23
 */
@Service
public class EhsCheckTableService {

    @Autowired
    private EhsCheckTableRepository repository;

    @Autowired
    private EhsCheckGroupRepository checkGroupRepository;

    @Autowired
    private EhsCheckItemRepository checkItemRepository;

    @Autowired
    private EhsTaskCategoryService taskCategoryService;

    @Autowired
    private EhsTaskCategoryRepository taskCategoryRepository;

    @Autowired
    private EhsTplUnitcategoryService unitcategoryService;

    @Autowired
    private EhsUnitInfoService unitInfoService;

    /**
     * 查询检查表
     *
     * @param condition 查询条件DTO
     * @return List<CheckTableDto>
     * @author QuCheng Tech
     * @description 用于检查表维护模块和在工作任务模块中获取指定任务类型中的待选择检查表；
     * @since 2024/10/23
     */
    public List<CheckTableDto> queryTable(CheckTableQueryConditionDto condition) throws QCPromptException {
        //1.查询条件有效性验证
        if (condition == null)
            throw new QCPromptException("查询条件对象不能为空");
        if (StringUtils.isBlank(condition.getOrgcode()))
            throw new QCPromptException("组织代码不能为空");

        //2.构建查询条件
        LambdaQueryWrapper<EhsCheckTable> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EhsCheckTable::getOrgcode, condition.getOrgcode());
        //匹配分类代码
        if (StringUtils.isNotBlank(condition.getCatcode())) {
            if (Objects.isNull(taskCategoryService.get(condition.getCatcode())))
                throw new QCPromptException("指定的分类代码不存在");
            wrapper.eq(EhsCheckTable::getCatcode, condition.getCatcode());
        }
        //匹配状态；默认只查询状态正常的，可以指定查询状态
        if (StringUtils.isNotBlank(condition.getStatus())) {
            wrapper.eq(EhsCheckTable::getStatus, condition.getStatus());
        } else {
            wrapper.eq(EhsCheckTable::getStatus, ResourceStatusFlagEnum.NORMAL.getIndex());
        }
        //匹配关键字
        if (StringUtils.isNotBlank(condition.getKeywords())) {
            wrapper.and(q -> {
                q.like(EhsCheckTable::getTitle, condition.getKeywords()).or()
                        .like(EhsCheckTable::getDescription, condition.getKeywords());
            });
        }

        //排序，按标题名称
        wrapper.orderByAsc(EhsCheckTable::getTitle);

        //3.查询检查表
        List<EhsCheckTable> ens = repository.selectList(wrapper);
        if (CollectionUtils.isNotEmpty(ens)) {
            //需要根据检查表中的单元分类编码获取单元分类名称，并根据单元ID进行分解操作
            List<EhsTplUnitcategory> unitcategories = unitcategoryService.getAll();
            //需要根据检查表配置的单元ID获取对应的单元名称，在此查询一次获取全部单元信息
            List<EhsUnitDto> units = unitInfoService.getUnitByOrgCode(condition.getOrgcode());
            //可能存在有多个单元分类，在此进行1次查询全部单元分类
            List<CheckTableDto> result = new ArrayList<>();

            for (EhsCheckTable en : ens) {
                //获取到的检查表信息，还需要根据单元分类查询单元信息得到单元名称
                CheckTableDto tableDto = EhsCheckTableMapper.MAPPER.toDto(en);

                if (StringUtils.isNotBlank(en.getUccd())) {
                    if (unitcategories != null && unitcategories.size() > 0x0) {
                        Optional<EhsTplUnitcategory> unitcategory = unitcategories.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getUccd(), en.getUccd())).findFirst();
                        if (unitcategory != null && unitcategory.isPresent()) {
                            tableDto.setUcnm(unitcategory.get().getUcnm());
                        }
                    }
                }
                if (StringUtils.isNotBlank(en.getUnitids())) {
                    //从字符串分解单元ID集合
                    String[] unitIds = StringSplitUtil.Split(en.getUnitids(), true);
                    if (unitIds != null && unitIds.length > 0x0)
                        tableDto.setUnitids(unitIds);

                    List<String> unitNames = new ArrayList<>();
                    for (String unitid : unitIds) {
                        String unitname = "";
                        if (units != null && units.size() > 0x0) {
                            Optional<EhsUnitDto> unit = units.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getUnitid(), unitid)).findFirst();
                            if (unit != null && unit.isPresent())
                                unitname = unit.get().getUnitname();
                        }
                        unitNames.add(unitname);
                    }
                    tableDto.setUnitnames(unitNames.stream().toArray(String[]::new));
                }

                result.add(tableDto);
            }

            return result;
        }
        return null;
    }

    /**
     * 获取指定检查表完整信息
     *
     * @param id 检查表ID
     * @return CheckTableFullDto
     * @author QuCheng Tech
     * @since 2024/10/23
     */
    public CheckTableFullDto getTableFull(String id) throws QCPromptException {
        //1.获取指定检查表
        EhsCheckTable checkTable = repository.selectById(id);
        if (Objects.isNull(checkTable)) return null;
        if (checkTable.getStatus() == ResourceStatusFlagEnum.DISABLE
                || checkTable.getStatus() == ResourceStatusFlagEnum.DELETED)
            throw new QCPromptException("指定检查表已被禁用或删除");
        CheckTableFullDto result = EhsCheckTableMapper.MAPPER.toCheckTableFullDto(checkTable);
        //获取到的检查表信息，还需要根据单元分类查询单元信息得到单元名称
        if (StringUtils.isNotBlank(checkTable.getUccd())) {
            //查询单元分类信息
            try {
                TplUnitCategoryDto unitCategory = unitcategoryService.get(checkTable.getUccd());
                if (unitCategory != null)
                    result.setUcnm(unitCategory.getUcnm());
            } catch (QCPromptException e) {
                e.printStackTrace();
            }
        }
        if (StringUtils.isNotBlank(checkTable.getUnitids())) {
            //从字符串分解单元ID集合
            String[] unitIds = StringSplitUtil.Split(checkTable.getUnitids(), true);
            if (unitIds != null && unitIds.length > 0x0)
                result.setUnitids(unitIds);

            //需要根据检查表配置的单元ID获取对应的单元名称，在此查询一次获取全部单元信息
            List<EhsUnitDto> units = unitInfoService.getUnitByOrgCode(checkTable.getOrgcode());

            List<String> unitNames = new ArrayList<>();
            for (String unitid : unitIds) {
                String unitname = "";
                if (units != null && units.size() > 0x0) {
                    Optional<EhsUnitDto> unit = units.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getUnitid(), unitid)).findFirst();
                    if (unit != null && unit.isPresent())
                        unitname = unit.get().getUnitname();
                }
                unitNames.add(unitname);
            }
            result.setUnitnames(unitNames.stream().toArray(String[]::new));
        }

        //2.获取指定检查表的检查项分组
        LambdaQueryWrapper<EhsCheckGroup> groupWrapper = new LambdaQueryWrapper<>();
        groupWrapper.eq(EhsCheckGroup::getTableid, id)
                .eq(EhsCheckGroup::getStatus, ResourceStatusFlagEnum.NORMAL.getIndex());
        //检查表分组排序
        groupWrapper.orderByAsc(EhsCheckGroup::getOdr).orderByAsc(EhsCheckGroup::getTableid);
        List<EhsCheckGroup> checkGroups = checkGroupRepository.selectList(groupWrapper);
        if (CollectionUtils.isEmpty(checkGroups)) return result;
        List<CheckGroupFullDto> groups = EhsCheckGroupMapper.MAPPER.toCheckGroupFullDtoList(checkGroups);

        //3.获取指定检查表的所有检查项
        LambdaQueryWrapper<EhsCheckItem> itemWrapper = new LambdaQueryWrapper<>();
        itemWrapper.eq(EhsCheckItem::getTableid, id)
                .eq(EhsCheckItem::getStatus, ResourceStatusFlagEnum.NORMAL.getIndex());
        //检查项排序
        itemWrapper.orderByAsc(EhsCheckItem::getOdr).orderByAsc(EhsCheckItem::getTableid);
        List<EhsCheckItem> checkItems = checkItemRepository.selectList(itemWrapper);
        if (CollectionUtils.isNotEmpty(checkItems)) {
            List<CheckItemDto> allItems = EhsCheckItemMapper.MAPPER.toDtoList(checkItems);

            //将对应分组的分组项设置到每个分组的items中
            for (CheckGroupFullDto group : groups) {
                List<CheckItemDto> items = allItems.stream().filter(item ->
                        item.getGroupid().equals(group.getGroupid())).collect(Collectors.toList());
                group.setItems(items);
            }
        }

        result.setGroups(groups);

        return result;
    }

    /**
     * 获取指定检查表
     *
     * @param id 检查表ID
     * @return CheckTableDto
     * @author QuCheng Tech
     * @since 2024/10/24
     */
    public CheckTableDto get(String id) {
        EhsCheckTable en = repository.selectById(id);
        if (Objects.nonNull(en)) {
            //获取到的检查表信息，还需要根据单元分类查询单元信息得到单元名称
            CheckTableDto result = EhsCheckTableMapper.MAPPER.toDto(en);

            if (StringUtils.isNotBlank(en.getUccd())) {
                //查询单元分类信息
                try {
                    TplUnitCategoryDto unitCategory = unitcategoryService.get(en.getUccd());
                    if (unitCategory != null)
                        result.setUcnm(unitCategory.getUcnm());
                } catch (QCPromptException e) {
                    e.printStackTrace();
                }
            }
            if (StringUtils.isNotBlank(en.getUnitids())) {
                //从字符串分解单元ID集合
                String[] unitIds = StringSplitUtil.Split(en.getUnitids(), true);
                if (unitIds != null && unitIds.length > 0x0)
                    result.setUnitids(unitIds);

                //需要根据检查表配置的单元ID获取对应的单元名称，在此查询一次获取全部单元信息
                List<EhsUnitDto> units = unitInfoService.getUnitByOrgCode(en.getOrgcode());

                List<String> unitNames = new ArrayList<>();
                for (String unitid : unitIds) {
                    String unitname = "";
                    if (units != null && units.size() > 0x0) {
                        Optional<EhsUnitDto> unit = units.stream().filter(p -> StringUtils.equalsIgnoreCase(p.getUnitid(), unitid)).findFirst();
                        if (unit != null && unit.isPresent())
                            unitname = unit.get().getUnitname();
                    }
                    unitNames.add(unitname);
                }
                result.setUnitnames(unitNames.stream().toArray(String[]::new));
            }

            return result;
        }
        return null;
    }

    /**
     * 新增检查表
     *
     * @param dto 新增对象DTO
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @since 2024/10/24
     */
    public String add(CheckTableDto dto) {
        //1.DTO有效性验证
        if (dto == null)
            return QCUnifyReturnValue.Warn("新增的检查表对象不能为空");
        if (StringUtils.isBlank(dto.getOrgcode()))
            return QCUnifyReturnValue.Warn("组织代码不能为空");
        if (StringUtils.isBlank(dto.getCatcode()))
            return QCUnifyReturnValue.Warn("分类代码不能为空");
        if (StringUtils.isBlank(dto.getTitle()))
            return QCUnifyReturnValue.Warn("标题不能为空");
        if (StringUtils.isBlank(dto.getUccd()))
            return QCUnifyReturnValue.Warn("单元分类不能为空");

        EhsTaskCategory category = taskCategoryRepository.selectById(dto.getCatcode());
        if (Objects.isNull(category)) return QCUnifyReturnValue.Warn("指定分类信息不存在");

        //2.dto -> entity
        EhsCheckTable en = EhsCheckTableMapper.MAPPER.dtoToEntity(dto);
        //判断转换后的检查表中的单元分类是否正确，是否存在
        if (unitcategoryService.isExist(en.getUccd()) == false)
            return QCUnifyReturnValue.Warn("单元分类不存在");

        //新增时自动生成检查表ID
        en.setTableid(IdentifierUtil.randomUUID());

        //3.保存信息
        if (repository.insert(en) < 0x1) {
            return QCUnifyReturnValue.Warn("保存失败");
        }
        return QCUnifyReturnValue.Success();
    }

    /**
     * 修改检查表
     *
     * @param dto 修改对象DTO
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @since 2024/10/24
     */
    public String update(CheckTableDto dto) {
        //1.DTO有效性验证
        if (dto == null)
            return QCUnifyReturnValue.Warn("修改的检查表对象不能为空");
        if (StringUtils.isBlank(dto.getTableid()))
            return QCUnifyReturnValue.Warn("检查表ID不能为空");
        if (StringUtils.isBlank(dto.getOrgcode()))
            return QCUnifyReturnValue.Warn("组织代码不能为空");
        if (StringUtils.isBlank(dto.getCatcode()))
            return QCUnifyReturnValue.Warn("分类代码不能为空");
        if (StringUtils.isBlank(dto.getTitle()))
            return QCUnifyReturnValue.Warn("标题不能为空");
        if (StringUtils.isBlank(dto.getUccd()))
            return QCUnifyReturnValue.Warn("单元分类不能为空");

        if (!isExist(dto.getTableid()))
            return QCUnifyReturnValue.Warn("指定检查表信息不存在");
        
        EhsTaskCategory category = taskCategoryRepository.selectById(dto.getCatcode());
        if (Objects.isNull(category))
            return QCUnifyReturnValue.Warn("指定分类信息不存在");

        //2.dto -> entity
        EhsCheckTable en = EhsCheckTableMapper.MAPPER.dtoToEntity(dto);
        //判断转换后的检查表中的单元分类是否正确，是否存在
        if (unitcategoryService.isExist(en.getUccd()) == false)
            return QCUnifyReturnValue.Warn("单元分类不存在");

        //3.更新数据
        repository.updateById(en);
        return QCUnifyReturnValue.Success();
    }

    /**
     * 删除检查表
     *
     * @param id            检查表ID
     * @param isLogicDelete 是否为逻辑删除；为true表示逻辑删除--修改记录标记，为false表示物理删除--从数据库表中删除记录
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @description 同时删除检查项分组和检查项
     * @since 2024/10/24
     */
    public String delete(String id, boolean isLogicDelete) {

        if (isLogicDelete) {
            //逻辑删除：修改检查表的状态
            EhsCheckTable en = repository.selectById(id);
            en.setStatus(ResourceStatusFlagEnum.DELETED);
            repository.updateById(en);
        } else {
            //物理删除：同时删除检查项分组和检查项
            //获取指定检查表的检查项分组，删除分组
            LambdaQueryWrapper<EhsCheckGroup> groupWrapper = new LambdaQueryWrapper<>();
            groupWrapper.eq(EhsCheckGroup::getTableid, id);
            List<EhsCheckGroup> checkGroups = checkGroupRepository.selectList(groupWrapper);

            //获取指定检查表、指定分组的检查项，删除检查项
            if (CollectionUtils.isNotEmpty(checkGroups)) {
                List<String> groupIds = checkGroups.stream().map(EhsCheckGroup::getGroupid).collect(Collectors.toList());
                LambdaQueryWrapper<EhsCheckItem> itemWrapper = new LambdaQueryWrapper<>();
                itemWrapper.eq(EhsCheckItem::getTableid, id)
                        .in(EhsCheckItem::getGroupid, groupIds);
                List<EhsCheckItem> checkItems = checkItemRepository.selectList(itemWrapper);
                if (CollectionUtils.isNotEmpty(checkItems)) {
                    for (EhsCheckItem item : checkItems) {
                        checkItemRepository.deleteById(item);
                    }
                }

                for (EhsCheckGroup group : checkGroups) {
                    checkGroupRepository.deleteById(group);
                }
            }

            //删除检查表
            repository.deleteById(id);
        }

        return QCUnifyReturnValue.Success();
    }

    /**
     * 指定检查表是否存在
     *
     * @param id 检查表ID
     * @return true表示存在，false表示不存在
     */
    public boolean isExist(String id) {
        EhsCheckTable en = repository.selectById(id);

        if (Objects.nonNull(en)) return true;

        return false;
    }
}
